package service

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"math/rand"
	"organoid_public/domain/sample/repository"
	"organoid_public/global"
	"organoid_public/pkg/logger"
	"strconv"
	"strings"
	"time"
)

/**
领域服务，可以处理复杂的业务逻辑，暴露给应用层
*/

type UserService struct {
	log           logger.Logger
	repo          repository.UserRepo
	LoginAuthRepo repository.LoginAuth
}

type JwtTokenObj struct {
	Uid  int
	Name string
	jwt.StandardClaims
}

func NewUserService(userRepository repository.UserRepo, LoginAuthRepo repository.LoginAuth) UserServiceInterface {
	return &UserService{repo: userRepository, LoginAuthRepo: LoginAuthRepo}
}

// 登录
func (u *UserService) LoginIn(username, password string) (string, error) {
	user, err := u.repo.GetUsersByUserName(username)
	if err != nil {
		return "", err
	}
	if user.Id <= 0 {
		return "", errors.New("账号未注册")
	}
	h := md5.New()
	h.Write([]byte(password))
	password = hex.EncodeToString(h.Sum(nil))
	if user.Password != password {
		return "", errors.New("密码错误")
	}

	var expDuration = time.Duration(global.GinConfig.Token.ExpireTime) * time.Hour
	var writerBuf = strings.Builder{}
	writerBuf.WriteString(strconv.Itoa(rand.Intn(999)))
	writerBuf.WriteString("-")
	writerBuf.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
	writerBuf.WriteString("-")
	writerBuf.WriteString(strconv.Itoa(user.Id))
	cla := JwtTokenObj{
		Uid:  user.Id,
		Name: user.UserName,
		StandardClaims: jwt.StandardClaims{
			Audience:  global.GinConfig.Token.Audience,
			ExpiresAt: time.Now().Add(expDuration).Unix(),
			IssuedAt:  time.Now().Unix(),
			Id:        writerBuf.String(),
			Issuer:    global.GinConfig.Token.Issuer,
			NotBefore: time.Now().Add(time.Duration(10) * time.Second).Unix(),
			Subject:   "note of auth",
		},
	}
	claimsObj := jwt.NewWithClaims(jwt.SigningMethodHS256, cla)
	//将token入库
	result := u.LoginAuthRepo.AddAuth(writerBuf.String())
	if !result {
		return "", errors.New("token create fail")
	}
	return claimsObj.SignedString([]byte(global.GinConfig.Token.Secret))
}

// 令牌校验
func (u *UserService) CheckAuth(token string) (*JwtTokenObj, error) {
	jwtTokenObj := &JwtTokenObj{}
	jwtToken, err := jwt.ParseWithClaims(token, jwtTokenObj, func(t *jwt.Token) (interface{}, error) {

		return []byte(global.GinConfig.Token.Secret), nil
	})
	if err != nil {
		return nil, err
	}
	if jwtToken.Valid {
		result := u.LoginAuthRepo.FindAuth(jwtToken.Claims.(*JwtTokenObj).Id)
		if !result {
			return nil, errors.New("token invalid")
		}
		return jwtTokenObj, nil
	}

	return nil, errors.New("token invalid")
}

func (u *UserService) LoginOut(tokenId string) (bool, error) {
	result := u.LoginAuthRepo.DelAuth(tokenId)
	if !result {
		return result, errors.New("操作失败")
	}
	return result, nil
}

func (u *UserService) refreshToken() {

}

func (u *UserService) HeadImgUpload(params *repository.HeadImgParams) error {
	return nil
}
